#include "King.h"
#include "../Game/Engine.h"
#include "../Board/Chessboard.h"
#include "../Board/Square.h"

namespace Core
{
	King::King(Player * player, Square * square)
		:Piece(player, square)
	{
	}


	King::~King(void)
	{
	}

	std::string King::name() const { return "King"; }
	ChType King::type() const { return ChType::ChKing; }

	//Move * King::canMove(Square * dst)
	//{
	//	Move * mv = Move::createMove(this, dst);

	//	return mv;
	//}


	void King::updateValidMoves()
	{
		int r = this->square()->row();
		int c = this->square()->column();
		
		// mishe ba FOR nevesht (baraye vozouhe code intori neveshtam)
		considerForValidMove(r+1, c+1);
		considerForValidMove(r+1, c-1);
		considerForValidMove(r-1, c+1);
		considerForValidMove(r-1, c-1);
		considerForValidMove(r+1, c);
		considerForValidMove(r-1, c);
		considerForValidMove(r, c+1);
		considerForValidMove(r, c-1);

		// consider CASTLING move possiblity
		const Chessboard * brd = Engine::instance()->chessboard();
		if(!hasNotMovedYet() || (color() == ChWhite && Engine::instance()->status() == ChStatus::ChWhiteIsChecked) ||
			(color() == ChBlack && Engine::instance()->status() == ChStatus::ChBlackIsChecked))
			return;

		Move * mv = NULL;
		Piece * rookLeft = brd->at(r, 0)->piece();
		mv = new Move(this, brd->at(r, c-2));
		mv->action(ChCastling);
		if(rookLeft != NULL && rookLeft->type() == ChRook && rookLeft->color() == this->color() && rookLeft->hasNotMovedYet())
		{
			Piece * p = brd->findPieceDirect(r, c, rookLeft->square()->row(), rookLeft->square()->column());
			if(p == rookLeft)
			{
				// see if the path is under attack
				if(brd->underAttackBy(r, c-1, color()) == NULL/* && brd->underAttackBy(r, c-2, color()) == NULL*/)
				{
					mv->prevMove(new Move(rookLeft, brd->at(r, 3)));
					mv->prevMove()->action(ChCastling);
					mv->prevMove()->nextMove(mv);
					_validMoves[mv->to()->key()] =  mv;
				}
			}
		}

		Piece * rookRght = brd->at(r, 7)->piece();
		mv = new Move(this, brd->at(r, c+2));
		mv->action(ChCastling);
		if(rookRght != NULL && rookRght->type() == ChRook && rookRght->color() == this->color() && rookRght->hasNotMovedYet())
		{
			Piece * p = brd->findPieceDirect(r, c, rookRght->square()->row(), rookRght->square()->column());
			if(p == rookRght)
			{
				// see if the path is under attack
				if(brd->underAttackBy(r, c+1, color()) == NULL/* && brd->underAttackBy(r, c+2, color()) == NULL*/)
				{
					mv->prevMove(new Move(rookRght, brd->at(r, 5)));
					mv->prevMove()->action(ChCastling);
					mv->prevMove()->nextMove(mv);
					_validMoves[mv->to()->key()] =  mv;
				}
			}
		}
	}

	void King::considerForValidMove(int r2, int c2)
	{
		const Chessboard * brd = Engine::instance()->chessboard();
		try
		{
			Move * mv = new Move(this, brd->at(r2, c2));
			if(checkDestination(mv) /*&& brd->underAttackBy(r2, c2, color()) == NULL*/)
				_validMoves[mv->to()->key()] = mv;
		}
		catch(...) { /* bypass this move */ }
	}

}
